package com.chenjian.annotation.custom;

import com.chenjian.annotation.ClassPathPackageScanner;
import com.chenjian.annotation.custom.anno.CustomAutowired;
import com.chenjian.annotation.custom.anno.CustomService;
import com.chenjian.annotation.custom.anno.CustomTransactional;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自定义been上下文
 *
 * 核心类
 *
 * <p>
 * 单例模式
 */
public class CustomContext {

    private Set<Class<?>> hasSet = new HashSet<>();
    private static CustomContext customContext = new CustomContext();

    private ConcurrentHashMap<String, Object> beens = new ConcurrentHashMap<>(2);

    public static CustomContext getCustomContext() {
        return customContext;
    }

    public ConcurrentHashMap<String, Object> getCustomContextMap() {
        return beens;
    }

    public void customContextInit(String basePackagePath) throws IOException {
        //扫描包，提取所有接口和类
        //扫描,获取所有class文件
        ClassPathPackageScanner scanner = new ClassPathPackageScanner();
        Set<Class<?>> classSet = scanner.getFullyQualifiedClassNameList(basePackagePath);
        //动态代理创建对象
        try {
            //基础been处理
            doCreateBeens(classSet);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        //di注入
        try {
            //依赖注入
            doDi();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        //事务控制
        doTransational();
    }

    private void doTransational() {

        //包含注解类class
        for (Class<?> aClass : hasSet) {
            //检测事务注解
            boolean annotationPresent = aClass.isAnnotationPresent(CustomTransactional.class);
            if (annotationPresent) {
                //注解支持（仅支持类注释）
                CustomService annotation = aClass.getAnnotation(CustomService.class);
                if (null != annotation) {
                    String beanName = annotation.value();
                    if ("".equals(beanName)) {
                        beanName = aClass.getName();
                    }
                    //获取实例化对象，从been池中获取对象
                    Object obj = beens.get(beanName);
                   /* Class<?>[] interfaces = obj.getClass().getInterfaces();*/
                    //构建增强逻辑
                    Object bean = DefaultCustomBeenFactory.getInstance().getBean(obj);
                    //替换been对象，将普通been替换成代理对象，实现逻辑增强
                    beens.put(beanName, bean);
                }
            }
        }

    }


    private void doCreateBeens(Set<Class<?>> classSet) throws IllegalAccessException, InstantiationException {
        for (Class<?> aClass : classSet) {
            //检测类注解
            boolean annotation = aClass.isAnnotationPresent(CustomService.class);
            if (annotation) {
                //获取类注解及其配置的属性
                CustomService customService = aClass.getAnnotation(CustomService.class);
                if (null != customService) {
                    String beanName = customService.value();
                    //默认为""，默认用全类名做为been id，如果有value值，则用value值作为been id
                    if ("".equals(beanName)) {
                        beanName = aClass.getName();
                    }

                    /*Class<?>[] interfaces = aClass.getInterfaces();*/
                   /* Object instance = null;*/
                    Object newInstance = aClass.newInstance();
                    //核心been池，装载ioc创建的所有对象
                    beens.put(beanName, newInstance);
                    hasSet.add(aClass);
                }
            }
        }
    }

    //注入
    private void doDi() throws IllegalAccessException {
        //hasSet保存的是有service注解的类
        for (Class<?> aClass : hasSet) {
            CustomService annotation = aClass.getAnnotation(CustomService.class);
            String value = annotation.value();
            if ("".equals(value)) {
                value = aClass.getName();
            }
            //获取到相应的对象，从been池中获取的对象
            Object obj = beens.get(value);
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                //java反射获取私有化字段，暴力访问
                field.setAccessible(true);
                boolean annotationPresent = field.isAnnotationPresent(CustomAutowired.class);
                if (annotationPresent) {
                    Class<?> fieldType = field.getType();
                    CustomService annotation1 = fieldType.getAnnotation(CustomService.class);
                    String value1 = annotation1.value();
                    if ("".equals(value1)) {
                        value1 = fieldType.getName();
                    }
                    //从been池中获取依赖的对象
                    Object o = beens.get(value1);
                    //暴力反射，向私有字段辅助，完成对象构建
                    field.set(obj, o);
                }
            }
        }

    }

}
